package cn.qicaiwang.open.app.server.Impl;


import cn.qicaiwang.open.app.dto.FeeCalculationDTO;
import cn.qicaiwang.open.app.dto.InterestCalculationDTO;
import cn.qicaiwang.open.app.dto.InterestRateConversionDTO;
import cn.qicaiwang.open.app.dto.WorkInjuryCompensationDTO;
import cn.qicaiwang.open.app.entity.CalculationRecord;
import cn.qicaiwang.open.app.mapper.CalculationRecordMapper;
import cn.qicaiwang.open.app.server.LegalCalculationService;
import cn.qicaiwang.open.common.utils.JsonUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;

/**
 * 法律计算服务实现类
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class LegalCalculationServiceImpl extends ServiceImpl<CalculationRecordMapper, CalculationRecord>
        implements LegalCalculationService {

    private final CalculationRecordMapper recordMapper;
    private final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BigDecimal calculateWorkInjuryCompensation(WorkInjuryCompensationDTO dto) {
        // 1. 计算一次性伤残补助金
        BigDecimal disabilityCompensation = calculateDisabilityCompensation(
                dto.getMonthlySalary(), dto.getDisabilityLevel());

        // 2. 计算住院伙食补助费 (按30元/天)
        BigDecimal hospitalizationSubsidy = new BigDecimal(dto.getHospitalizationDays() * 30);

        // 3. 计算护理费 (按100元/天)
        BigDecimal nursingFee = new BigDecimal(dto.getNursingDays() * 100);

        // 4. 计算总赔偿金额
        BigDecimal total = disabilityCompensation
                .add(dto.getMedicalExpenses())
                .add(hospitalizationSubsidy)
                .add(nursingFee)
                .add(dto.getTransportationFee());

        // 5. 保存计算记录
        saveCalculationRecord("工伤赔偿", total, dto);

        return total.setScale(2, RoundingMode.HALF_UP);
    }

    // 计算一次性伤残补助金（私有方法）
    private BigDecimal calculateDisabilityCompensation(BigDecimal monthlySalary, int disabilityLevel) {
        switch (disabilityLevel) {
            case 1: return monthlySalary.multiply(new BigDecimal(27));
            case 2: return monthlySalary.multiply(new BigDecimal(25));
            case 3: return monthlySalary.multiply(new BigDecimal(23));
            case 4: return monthlySalary.multiply(new BigDecimal(21));
            case 5: return monthlySalary.multiply(new BigDecimal(18));
            case 6: return monthlySalary.multiply(new BigDecimal(16));
            case 7: return monthlySalary.multiply(new BigDecimal(13));
            case 8: return monthlySalary.multiply(new BigDecimal(11));
            case 9: return monthlySalary.multiply(new BigDecimal(9));
            case 10: return monthlySalary.multiply(new BigDecimal(7));
            default: throw new IllegalArgumentException("无效的伤残等级");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BigDecimal calculateInterest(InterestCalculationDTO dto) {
        // 1. 解析日期
        LocalDate startDate = LocalDate.parse(dto.getStartDate(), dateFormatter);
        LocalDate endDate = LocalDate.parse(dto.getEndDate(), dateFormatter);

        // 2. 计算天数差
        //int days = Period.between(startDate, endDate).getDays();
        int days =(int) ChronoUnit.DAYS.between(startDate, endDate);

        //转换为数字类型

        // 3. 计算日利率
        BigDecimal dailyRate = dto.getAnnualRate()
                .divide(BigDecimal.valueOf(100), 6, RoundingMode.HALF_UP)
                .divide(BigDecimal.valueOf(365), 6, RoundingMode.HALF_UP);

        // 4. 计算利息金额
        BigDecimal interest = dto.getPrincipal()
                .multiply(dailyRate)
                .multiply(BigDecimal.valueOf(days))
                .setScale(2, RoundingMode.HALF_UP);
        log.info("计算利息金额为:{}",interest);
        // 5. 保存计算记录
        saveCalculationRecord("利息计算", interest, dto);

        return interest;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BigDecimal calculateLitigationFee(FeeCalculationDTO dto) {
        // 诉讼费分段计算标准
        BigDecimal fee = calculateFeeByAmount(dto.getAmount(),
                new BigDecimal(50),
                new BigDecimal("0.025"), new BigDecimal(200),
                new BigDecimal("0.02"), new BigDecimal(300),
                new BigDecimal("0.015"), new BigDecimal(1300));

        saveCalculationRecord("诉讼费计算", fee, dto);
        return fee.setScale(2, RoundingMode.HALF_UP);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BigDecimal calculateArbitrationFee(FeeCalculationDTO dto) {
        // 校验输入金额
        if (dto.getAmount() == null || dto.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
            throw new IllegalArgumentException("金额必须大于0");
        }

        // 分段计算仲裁费（示例分段标准）
        BigDecimal fee = BigDecimal.ZERO;
        BigDecimal remainingAmount = dto.getAmount();

        // 第一段：0-100元部分
        BigDecimal segment1 = remainingAmount.min(new BigDecimal(100));
        fee = fee.add(segment1.multiply(new BigDecimal("0.03")));
        remainingAmount = remainingAmount.subtract(segment1);

        // 第二段：100-500元部分
        if (remainingAmount.compareTo(BigDecimal.ZERO) > 0) {
            BigDecimal segment2 = remainingAmount.min(new BigDecimal(400)); // 500-100=400
            fee = fee.add(segment2.multiply(new BigDecimal("0.025")));
            remainingAmount = remainingAmount.subtract(segment2);
        }

        // 第三段：500-800元部分
        if (remainingAmount.compareTo(BigDecimal.ZERO) > 0) {
            BigDecimal segment3 = remainingAmount.min(new BigDecimal(300)); // 800-500=300
            fee = fee.add(segment3.multiply(new BigDecimal("0.02")));
            remainingAmount = remainingAmount.subtract(segment3);
        }

        // 第四段：800-1500元部分
        if (remainingAmount.compareTo(BigDecimal.ZERO) > 0) {
            BigDecimal segment4 = remainingAmount.min(new BigDecimal(700)); // 1500-800=700
            fee = fee.add(segment4.multiply(new BigDecimal("0.015")));
            remainingAmount = remainingAmount.subtract(segment4);
        }

        // 超过1500元部分
        if (remainingAmount.compareTo(BigDecimal.ZERO) > 0) {
            fee = fee.add(remainingAmount.multiply(new BigDecimal("0.01")));
        }

        // 保存计算记录
        saveCalculationRecord("仲裁费计算", fee, dto);

        // 四舍五入保留2位小数
        return fee.setScale(2, RoundingMode.HALF_UP);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BigDecimal calculatePreservationFee(FeeCalculationDTO dto) {
        BigDecimal amount = dto.getAmount();
        BigDecimal fee = BigDecimal.ZERO;

        // 保全费分段计算标准
        if (amount.compareTo(new BigDecimal(1000)) <= 0) {
            fee = new BigDecimal(30);
        } else if (amount.compareTo(new BigDecimal(100000)) <= 0) {
            fee = amount.multiply(new BigDecimal("0.01")).add(new BigDecimal(20));
        } else if (amount.compareTo(new BigDecimal(1000000)) <= 0) {
            fee = amount.multiply(new BigDecimal("0.005")).add(new BigDecimal(520));
        } else {
            fee = amount.multiply(new BigDecimal("0.0005")).add(new BigDecimal(5520));
            fee = fee.min(new BigDecimal(5000)); // 最高不超过5000元
        }

        fee = fee.max(new BigDecimal(30)); // 最低不低于30元

        saveCalculationRecord("保全费计算", fee, dto);
        return fee.setScale(2, RoundingMode.HALF_UP);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BigDecimal calculateExecutionFee(FeeCalculationDTO dto) {
        BigDecimal amount = dto.getAmount();
        BigDecimal fee = BigDecimal.ZERO;

        // 执行申请费分段计算标准
        if (amount.compareTo(new BigDecimal(10000)) <= 0) {
            fee = new BigDecimal(50);
        } else if (amount.compareTo(new BigDecimal(500000)) <= 0) {
            fee = amount.multiply(new BigDecimal("0.015")).subtract(new BigDecimal(100));
        } else if (amount.compareTo(new BigDecimal(5000000)) <= 0) {
            fee = amount.multiply(new BigDecimal("0.01")).add(new BigDecimal(2400));
        } else if (amount.compareTo(new BigDecimal(10000000)) <= 0) {
            fee = amount.multiply(new BigDecimal("0.005")).add(new BigDecimal(27400));
        } else {
            fee = amount.multiply(new BigDecimal("0.001")).add(new BigDecimal(67400));
        }

        fee = fee.max(new BigDecimal(50)); // 最低不低于50元

        saveCalculationRecord("执行申请费计算", fee, dto);
        return fee.setScale(2, RoundingMode.HALF_UP);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BigDecimal convertInterestRate(InterestRateConversionDTO dto) {
        BigDecimal rate = dto.getRate();
        String from = dto.getFromType().toLowerCase();
        String to = dto.getToType().toLowerCase();

        // 1. 先转换为年利率
        BigDecimal annualRate;
        switch (from) {
            case "annual":
                annualRate = rate;
                break;
            case "monthly":
                annualRate = rate.multiply(BigDecimal.valueOf(12));
                break;
            case "daily":
                annualRate = rate.multiply(BigDecimal.valueOf(365));
                break;
            default:
                throw new IllegalArgumentException("无效的利率类型");
        }

        // 2. 从年利率转换为目标类型
        switch (to) {
            case "annual":
                return annualRate;
            case "monthly":
                return annualRate.divide(BigDecimal.valueOf(12), 6, RoundingMode.HALF_UP);
            case "daily":
                return annualRate.divide(BigDecimal.valueOf(365), 6, RoundingMode.HALF_UP);
            default:
                throw new IllegalArgumentException("无效的利率类型");
        }
    }

    /**
     * 通用费用计算方法（私有方法）
     */
    private BigDecimal calculateFeeByAmount(BigDecimal amount,
                                            BigDecimal baseFee,
                                            BigDecimal rate1, BigDecimal sub1,
                                            BigDecimal rate2, BigDecimal add2,
                                            BigDecimal rate3, BigDecimal add3) {
        if (amount.compareTo(BigDecimal.valueOf(10000)) <= 0) {
            return baseFee;
        } else if (amount.compareTo(BigDecimal.valueOf(100000)) <= 0) {
            return amount.multiply(rate1).subtract(sub1);
        } else if (amount.compareTo(BigDecimal.valueOf(200000)) <= 0) {
            return amount.multiply(rate2).add(add2);
        } else {
            return amount.multiply(rate3).add(add3);
        }
    }

    /**
     * 保存计算记录（私有方法）
     */
    private void saveCalculationRecord(String type, BigDecimal result, Object params) {
        CalculationRecord record = new CalculationRecord();
        record.setCalculationType(type);
        record.setAmount(getAmountFromParams(params));
        record.setResult(result);
        record.setCreateTime(LocalDateTime.now());
        record.setParamsJson(JsonUtil.toJson(params));

        recordMapper.insert(record);
    }

    /**
     * 从参数对象中提取金额（私有方法）
     */
    private BigDecimal getAmountFromParams(Object params) {
        if (params instanceof WorkInjuryCompensationDTO) {
            return ((WorkInjuryCompensationDTO) params).getMonthlySalary();
        } else if (params instanceof InterestCalculationDTO) {
            return ((InterestCalculationDTO) params).getPrincipal();
        } else if (params instanceof FeeCalculationDTO) {
            return ((FeeCalculationDTO) params).getAmount();
        } else if (params instanceof InterestRateConversionDTO) {
            return ((InterestRateConversionDTO) params).getRate();
        }
        return BigDecimal.ZERO;
    }
}